package com.totoro.tygeneratedragonblock.manager;

import com.mojang.authlib.GameProfile;
import com.totoro.tygeneratedragonblock.TyGenerateDragonBlock;
import com.totoro.tygeneratedragonblock.constants.StaticSystemVarConst;
import com.totoro.tygeneratedragonblock.data.ChunkCoordinate;
import com.totoro.tygeneratedragonblock.pojo.BlockDefinition;
import com.totoro.tygeneratedragonblock.pojo.SpawnPoint;
import com.totoro.tygeneratedragonblock.utils.ColorUtil;
import com.totoro.tygeneratedragonblock.utils.StrUtil;
import eu.decentsoftware.holograms.api.DHAPI;
import lombok.Getter;
import net.minecraft.server.v1_12_R1.BlockPosition;
import net.minecraft.server.v1_12_R1.TileEntitySkull;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Totoro
 * @version 0.1.0
 * @date 2025/8/10 - 3:04
 * @description 刷新点管理器
 **/
public class SpawnersManager {

    private final TyGenerateDragonBlock plugin;

    private final LoggerManager logger;

    private final static File SPAWNERS_FOLDER = new File(TyGenerateDragonBlock.getInstance().getDataFolder().getPath() + StaticSystemVarConst.FILE_SEPARATOR + StaticSystemVarConst.SPAWNERS_FOLDER_DEFAULT_NAME);

    /* 存储方块刷新配置的map */
    @Getter private final Map<String, SpawnPoint> spawnPoints = new ConcurrentHashMap<>();

    /* 存储刷新点对应的刷新Id的map */
    @Getter private final Map<Location, String> locationToSpawnId = new ConcurrentHashMap<>();

    /* 存储所有生成方块的世界 */
    @Getter private final Set<String> targetWorlds = new HashSet<>();

    public SpawnersManager(TyGenerateDragonBlock plugin) {
        this.plugin = plugin;
        logger = plugin.getLoggerManager();
        initSpawnersFile();
        reloadSpawnersFile();
    }

    /**
     * 生成默认文件夹
     */
    public void initSpawnersFile() {
        // 如果文件不存在则创建
        if(! SPAWNERS_FOLDER.exists()) {
            SPAWNERS_FOLDER.mkdirs();
        }
    }


    /**
     * @author totoro
     * @description 放置方块，通过刷新点
     * @date  19:08
     * @param [spawn]
     * @return void
     **/
    public void placeSpawnBlock(SpawnPoint spawn) {
        BlockDefinition def = plugin.getBlocksManager().getBlockDefinitions().get(spawn.getBlockId());
        if (def == null) {
            plugin.getServer().getConsoleSender().sendMessage(StaticSystemVarConst.CONSOLE_PREFIX + (ColorUtil.color("&c无法找到方块定义: &e" + spawn.getBlockId())));
            return;
        }

        Location location = spawn.getLocation();
        if (location.getWorld() == null) {
            plugin.getServer().getConsoleSender().sendMessage(StaticSystemVarConst.CONSOLE_PREFIX + (ColorUtil.color("&c无法找到该世界: &e" + spawn.getId())));
            return;
        }

        // 检查区块是否加载
        if (!location.getChunk().isLoaded()) {
            return;
        }

        Block block = location.getBlock();
        block.setType(Material.SKULL);

        // 创建自定义龙核方块
        GameProfile profile = plugin.getGameProfileCacheHandler().getCachedProfile(def);
        if (profile == null) return;
        try {
            CraftWorld craftWorld = (CraftWorld) location.getWorld();
            BlockPosition pos = new BlockPosition(
                    location.getBlockX(),
                    location.getBlockY(),
                    location.getBlockZ()
            );

            TileEntitySkull skullTile = (TileEntitySkull) craftWorld.getHandle().getTileEntity(pos);
            if (skullTile != null) {
                skullTile.setGameProfile(profile);
                skullTile.update();
                block.getState().update(true, true);
                // 记录位置到刷新点ID的映射
                logger.debug("当前坐标已经放置 " + spawn.getId() +" 的方块：" + location.toString());
                locationToSpawnId.put(location, spawn.getId());
                // 如果开启了DecentHolograms方块显示
                if (plugin.getConfigManager().getConfig().getEnableBlockNameDisplay() && StaticSystemVarConst.dependentDecentHologramsEnable) {
                    if(null == DHAPI.getHologram(StrUtil.toUniqueEnglish(spawn.getId()))) {
                        Location cloneLocation = location.clone();
                        cloneLocation.setX(cloneLocation.getX() + def.getNameDisplayLocation().getX());
                        cloneLocation.setY(cloneLocation.getY() + def.getNameDisplayLocation().getY());
                        cloneLocation.setZ(cloneLocation.getZ() + def.getNameDisplayLocation().getZ());
                        DHAPI.createHologram(StrUtil.toUniqueEnglish(spawn.getId()), cloneLocation, Collections.singletonList(def.getBlockName()));
                    }
                }
            }
        } catch (Exception e) {
            plugin.getLogger().log(java.util.logging.Level.SEVERE, ColorUtil.color("&c放置刷新点方块失败"), e);
        }
    }

    /**
     * @author totoro
     * @description 保存刷新点
     * @date  18:12
     * @param [spawnPoint]
     * @return void
     **/
    public Boolean saveSpawnersFile(SpawnPoint spawnPoint) {
        File spawnFile = new File(SPAWNERS_FOLDER.getPath() + StaticSystemVarConst.FILE_SEPARATOR + spawnPoint.getId() + ".yml");
        YamlConfiguration mainConfig = new YamlConfiguration();
        YamlConfiguration config = new YamlConfiguration();
        // 设置配置值
        config.set("blockId", spawnPoint.getBlockId());
        config.set("cooldown", spawnPoint.getCooldown());
        config.set("x", spawnPoint.getLocation().getBlockX());
        config.set("y", spawnPoint.getLocation().getBlockY());
        config.set("z", spawnPoint.getLocation().getBlockZ());
        config.set("world", spawnPoint.getLocation().getWorld().getName());
        // 添加配置值
        mainConfig.set(spawnPoint.getId(), config);
        // 保存文件
        try {
            mainConfig.save(spawnFile);
            // 添加刷新点Map
            spawnPoints.put(spawnPoint.getId(), spawnPoint);
            // 放置方块
            placeSpawnBlock(spawnPoint);
            // 更新区块映射
            ChunkCoordinate chunkCoordinate = new ChunkCoordinate(spawnPoint.getLocation());
            plugin.getChunkMappingManager().getChunkSpawnMap().computeIfAbsent(chunkCoordinate, k -> ConcurrentHashMap.newKeySet()).add(spawnPoint.getId());
            plugin.getChunkMappingManager().getSpawnChunkMap().put(spawnPoint.getId(), chunkCoordinate);
            return true;
        } catch (IOException e) {
            plugin.getLogger().log(java.util.logging.Level.SEVERE, ColorUtil.color("&c保存刷新点配置失败: &e" + spawnPoint.getId()), e);
        }
        return false;
    }

    /**
     * @author totoro
     * @description 删除刷新点
     * @date  18:12
     * @param [spawnId]
     * @return void
     **/
    public void removeSpawnersFile(String spawnId) {
        SpawnPoint spawn = spawnPoints.get(spawnId);
        if (spawn == null) return;

        // 从区块映射中移除
        ChunkCoordinate chunkCoordinate = plugin.getChunkMappingManager().getSpawnChunkMap().get(spawnId);
        if (chunkCoordinate != null) {
            Set<String> spawnsInChunk = plugin.getChunkMappingManager().getChunkSpawnMap().get(chunkCoordinate);
            if (spawnsInChunk != null) {
                spawnsInChunk.remove(spawnId);
                if (spawnsInChunk.isEmpty()) {
                    plugin.getChunkMappingManager().getChunkSpawnMap().remove(chunkCoordinate);
                }
            }
            plugin.getChunkMappingManager().getSpawnChunkMap().remove(spawnId);
        }

        File spawnFile = new File(SPAWNERS_FOLDER.getPath() + StaticSystemVarConst.FILE_SEPARATOR + spawnId + ".yml");
        if(spawnFile.exists()) {
            spawnFile.delete();
        }

        // 从内存中移除
        spawnPoints.remove(spawnId);
        locationToSpawnId.remove(spawn.getLocation());
    }

    /**
     * @author totoro
     * @description 加载所有方块刷新点
     * @date  3:23
     * @param []
     * @return void
     **/
    public void reloadSpawnersFile() {
        initSpawnersFile();
        spawnPoints.clear();
        locationToSpawnId.clear();
        plugin.getChunkMappingManager().getChunkSpawnMap().clear();
        plugin.getChunkMappingManager().getSpawnChunkMap().clear();
        File[] spawnFiles = SPAWNERS_FOLDER.listFiles((dir, name) -> name.endsWith(".yml"));
        if(null != spawnFiles) {
            for (File spawnFile : spawnFiles) {
                YamlConfiguration spawnConfig = YamlConfiguration.loadConfiguration(spawnFile);
                String spawnPointsId = spawnConfig.getKeys(false).stream().findFirst().orElse(null);
                String message = StaticSystemVarConst.CONSOLE_PREFIX + ColorUtil.color(String.format("&c方块刷新点 [&e%s&c] 加载失败，请检查文件是否正确！", spawnFile.getName()));
                if(null == spawnPointsId) {
                    plugin.getServer().getConsoleSender().sendMessage(message);
                    continue;
                }
                if (! spawnConfig.isConfigurationSection(spawnPointsId)) {
                    plugin.getServer().getConsoleSender().sendMessage(message);
                    continue;
                }
                ConfigurationSection spawnPointsConfig = spawnConfig.getConfigurationSection(spawnPointsId);
                String blockId = spawnPointsConfig.getString("blockId");
                // 判断方块定义文件是否有该blockId
                if (! plugin.getBlocksManager().getBlockDefinitions().containsKey(blockId)) {
                    plugin.getServer().getConsoleSender().sendMessage(StaticSystemVarConst.CONSOLE_PREFIX + ColorUtil.color(String.format("&c方块刷新点 [&e%s&c] 加载失败，找不到对应的方块定义Id", spawnFile.getName())));
                    continue;
                }
                Double cooldown = spawnPointsConfig.getDouble("cooldown");
                int x = spawnPointsConfig.getInt("x");
                int y = spawnPointsConfig.getInt("y");
                int z = spawnPointsConfig.getInt("z");
                String worldName = spawnPointsConfig.getString("world");

                // 检查世界是否加载
                World world = Bukkit.getWorld(worldName);
                if (world == null) {
                    plugin.getServer().getConsoleSender().sendMessage(StaticSystemVarConst.CONSOLE_PREFIX +
                            ColorUtil.color(String.format("&c方块刷新点 [&e%s&c] 加载失败， 世界 [&e%s&c] 暂未加载！", spawnFile.getName(), worldName)));
                    continue;
                }
                targetWorlds.add(worldName);
                // 创建位置对象
                Location location = new Location(world, x, y, z);

                // 创建刷新点对象
                SpawnPoint spawn = new SpawnPoint(spawnPointsId, blockId, cooldown, location);
                spawnPoints.put(spawnPointsId, spawn);

                // 添加到区块映射
                ChunkCoordinate chunkCoordinate = new ChunkCoordinate(location);
                plugin.getChunkMappingManager().getChunkSpawnMap().computeIfAbsent(chunkCoordinate, k -> ConcurrentHashMap.newKeySet()).add(spawnPointsId);
                plugin.getChunkMappingManager().getSpawnChunkMap().put(spawnPointsId, chunkCoordinate);
            }
        }
    }

}
